import * as THREE from 'three'

export class MeshUtil {
  constructor() {
  }
  static createInstancedGeometry(geometry, num) {
    let instances = Math.floor(num * 0.5)
    // BufferGeometry 的实例化版本。
    let instancedGeometry = new THREE.InstancedBufferGeometry()
    // Copies the given InstancedBufferGeometry to this instance.
    instancedGeometry.copy(geometry)
    // 默认值是 Infinity。
    instancedGeometry.instanceCount = instances

    let aInstance = new Float32Array(4 * instances)
    let bInstance = new Float32Array(4 * instances)
    for (let i = 0; i < instances; i++) {
      // 圆角度 Circle angle
      aInstance[i * 4] = Math.random() * Math.PI * 2
      // 长方形角度 Torus tube angle
      aInstance[i * 4 + 1] = Math.random() * Math.PI * 2
      // 长方形大小 Torus tube scale
      aInstance[i * 4 + 2] = Math.random() * 4
      // 长方形角度 // Scale
      aInstance[i * 4 + 3] = 0.2 + Math.random() * Math.random()

      // 粒子本身旋转角度
      bInstance[i * 4] = Math.random() * Math.PI * 2
      // 设置随机颜色
      bInstance[i * 4 + 1] = Math.floor(Math.random() * 5)

    }
    // console.log(bInstance)
    instancedGeometry.setAttribute('aInstance', new THREE.InstancedBufferAttribute(aInstance, 4, false))
    instancedGeometry.setAttribute('bInstance', new THREE.InstancedBufferAttribute(bInstance, 4, false))

    return instancedGeometry
  }
  static create(geometry, mat, num = 400) {
    const mesh = new THREE.Mesh(MeshUtil.createInstancedGeometry(geometry, num), mat)
    // 当这个设置了的时候，每一帧渲染前都会检测这个物体是不是在相机的视椎体范围内。
    // 如果设置为false 物体不管是不是在相机的视椎体范围内都会渲染。默认为true。
    mesh.frustumCulled = false
    return mesh
  }
}

export class GeometryUtil {
  constructor() {
  }
  // new THREE.ConeGeometry( 5, 20, 32 ); // 棱锥

  static cone(size = 1) {

    return new THREE.ConeGeometry(
      size,
      size * 4,
      // size * 6.4
    )
  }

  static box(size = 1) {
    return new THREE.BoxGeometry(size, size, size)
  }

  static torus(size = 1) {
    return new THREE.TorusGeometry(size, size * 0.4)
  }

  static capsule(size = 1) {
    return new THREE.CapsuleGeometry( size, size);
  }

  // new THREE.CylinderGeometry( 5, 5, 20, 32 ); // 圆柱
  static cylinder(size = 1) {
    return new THREE.CylinderGeometry( size, size, size * 4, 32 );
  }

  // DodecahedronGeometry(radius : Float, detail : Integer)
  // radius — 十二面体的半径，默认值为1。
  // detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点，使其不再是一个十二面体。
  static dodecahedron(size = 1) {
    return new THREE.DodecahedronGeometry( size);
  }

  // IcosahedronGeometry(radius : Float, detail : Integer)
  // radius — 二十面体的半径，默认为1。
  // detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点，使其不再是一个二十面体。当这个值大于1的时候，实际上它将变成一个球体。
  static icosahedron(size = 1) {
    return new THREE.IcosahedronGeometry( size);
  }

  // 车削缓冲几何体
  // const points = [];
  // for ( let i = 0; i < 10; i ++ ) {
  // 	points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
  // }
  // const geometry = new THREE.LatheGeometry( points );
  // const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
  // const lathe = new THREE.Mesh( geometry, material );
  // scene.add( lathe );
  // points — 一个Vector2对象数组。每个点的X坐标必须大于0。 Default is an array with (0,-0.5), (0.5,0) and (0,0.5) which creates a simple diamond shape.
  // segments — 要生成的车削几何体圆周分段的数量，默认值是12。
  // phiStart — 以弧度表示的起始角度，默认值为0。
  // phiLength — 车削部分的弧度（0-2PI）范围，2PI将是一个完全闭合的、完整的车削几何体，小于2PI是部分的车削。默认值是2PI。
  static lathe(size = 1, type = 2) {
    const points = [];
    for ( let i = 0; i < 20; i ++ ) {
      // points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * size + (size * 0.5), ( i - 5 ) * (size * 0.2) ) );
      points.push( new THREE.Vector2( Math.sin( i * size * type ) * size + (size * 0.5), ( i - 5 ) * (size * 0.2) ) );
    }
    return new THREE.LatheGeometry( points );
  }


  // 八面缓冲几何体
  // OctahedronGeometry(radius : Float, detail : Integer)
  // radius — 八面体的半径，默认值为1。
  // detail — 默认值为0，将这个值设为一个大于0的数将会为它增加一些顶点，使其不再是一个八面体。
  static octahedron(size = 1) {
    return new THREE.OctahedronGeometry( size);
  }

  // 形状缓冲几何体（ShapeGeometry）
  // const x = 0, y = 0;
  //
  // const heartShape = new THREE.Shape();
  //
  // heartShape.moveTo( x + 5, y + 5 );
  // heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y );
  // heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 );
  // heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 );
  // heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 );
  // heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y );
  // heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 );
  //
  // const geometry = new THREE.ShapeGeometry( heartShape );
  // const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
  // const mesh = new THREE.Mesh( geometry, material ) ;
  // scene.add( mesh );
  static heart(size = 1) {
    const heartShape = new THREE.Shape();
    heartShape.moveTo( 5 * size * 0.2, 5 * size * 0.2 );
    const points = [
      5, 5, 4, 0, 0, 0,
      -6, 0,-6, 7,-6, 7,
      -6, 11,-3, 15.4, 5, 19,
      12, 15.4, 16, 11, 16, 7,
      16, 7, 16, 0, 10, 0,
      7, 0, 5, 5, 5, 5,
    ];

    for (let i = 0; i < Math.ceil(points.length / 6); i++) {
      heartShape.bezierCurveTo(
        points[i * 6] * size * 0.2,
        points[i * 6 + 1] * size * 0.2,
        points[i * 6 + 2] * size * 0.2,
        points[i * 6 + 3] * size * 0.2,
        points[i * 6 + 4] * size * 0.2,
        points[i * 6 + 5] * size * 0.2
      );
    }

    return new THREE.ShapeGeometry( heartShape );
  }
  // 球缓冲几何体
  // new THREE.SphereGeometry( 15, 32, 16 );
  // radius — 球体半径，默认为1。
  // widthSegments — 水平分段数（沿着经线分段），最小值为3，默认值为32。
  // heightSegments — 垂直分段数（沿着纬线分段），最小值为2，默认值为16。

  // 圆环缓冲扭结几何体
  // new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
  // radius - 圆环的半径，默认值为1。
  // tube — 管道的半径，默认值为0.4。
  // tubularSegments — 管道的分段数量，默认值为64。
  // radialSegments — 横截面分段数量，默认值为8。
  static torus_knot(size = 1) {
    return new THREE.TorusKnotGeometry( size, size * 7 / 10, 100, 16);
  }
}
